#include "Demo.h"
#include <windowsx.h>

//////////////////////////////////////////////////////////////////////////
// CDemoApp
//////////////////////////////////////////////////////////////////////////
CDemoApp::CDemoApp()
{

}

CDemoApp::~CDemoApp()
{

}

bool CDemoApp::InitInstance()
{
	m_pMainWnd = new CDemoWnd();
	m_pMainWnd->ShowWindow(SW_SHOW);
																   
	return true;
}

//////////////////////////////////////////////////////////////////////////
// CDemoWnd
//////////////////////////////////////////////////////////////////////////
#define MSGHANDLE(nMsg, MsgProc)  {(nMsg), (&CDemoWnd::MsgProc)}

const CDemoWnd::TMSGMAP CDemoWnd::MsgMapTable[] = {
	MSGHANDLE(WM_CREATE,	OnCreate),
	MSGHANDLE(WM_DESTROY,	OnDestroy), 
	MSGHANDLE(WM_PAINT,		OnPaint),
};

CDemoWnd::CDemoWnd(const TCHAR* szAppName)
{
	Create(szAppName, WS_OVERLAPPEDWINDOW, 0, 0, 800, 480, NULL);
}

CDemoWnd::~CDemoWnd()
{

}

LRESULT	 CDemoWnd::WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	for (int ii = 0; ii < sizeof(MsgMapTable) / sizeof(*MsgMapTable); ii++)
	{
		if (nMsg == MsgMapTable[ii].m_nMsg)
		{
			(this->*MsgMapTable[ii].m_MsgProc)(hWnd, nMsg, wParam, lParam);
			break;
		}
	}

	return __super::FinalWndProc(hWnd, nMsg, wParam, lParam);
}

LRESULT CDemoWnd::OnCreate(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	CenterWindow();

	return 0;
}

LRESULT CDemoWnd::OnDestroy(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	PostQuitMessage(0);

	return 0;
}

LRESULT CDemoWnd::OnPaint(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hDC = BeginPaint(hWnd, &ps);
	
	RECT rtGrids[4];

	PartitionGrid(hDC, rtGrids, 4);

	DemoSolidBrush(hDC, rtGrids[0]);
	
	EndPaint(hWnd, &ps);

	return 1;
}

void CDemoWnd::PartitionGrid(HDC hDC, RECT* prtGrids, int nGridCount)
{
	assert(0 < nGridCount);

	//--: Display current brush color
	COLORREF clColr = GetDCBrushColor(hDC);
	TCHAR szCurBrushInfo[256];
	_stprintf_s(szCurBrushInfo, 256, _T("   Current Brush Color: RGB(%d:%d:%d)"), GetRValue(clColr), GetGValue(clColr), GetBValue(clColr));
	TextOut(hDC, 0, 0, szCurBrushInfo, _tcslen(szCurBrushInfo));

	//--: Grids rect area
	RECT rtClient;
	GetClientRect(m_hWnd, &rtClient);
	InflateRect(&rtClient, -10, -10);
	OffsetRect(&rtClient, 0, 10);

	//==: calculate every grid rect and paint color
	HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, GetStockObject(DC_BRUSH));
	SetDCBrushColor(hDC, RGB(200, 200, 200));

	const int nGridH	= ((rtClient.bottom - rtClient.top) / nGridCount);
	for (int ii = 0; ii < nGridCount; ii++)
	{
		int nGridTop = rtClient.top + ii * nGridH;
		SetRect(&prtGrids[ii], rtClient.left, nGridTop, rtClient.right, nGridTop + nGridH);
		Rectangle(hDC, prtGrids[ii].left, prtGrids[ii].top, prtGrids[ii].right, prtGrids[ii].bottom);
	}
	SelectObject(hDC, hOldBrush);
	
	return;
}	

void CDemoWnd::DemoSolidBrush(HDC hDC, RECT& rtGrid)
{
	InflateRect(&rtGrid, -5, -5);

	int nSavedDC = SaveDC(hDC);

	const UINT nColorNum	= 256;
	LOGPALETTE* pLogPalette  = (LOGPALETTE*)new BYTE[sizeof(WORD) + sizeof(WORD) + nColorNum * sizeof(PALETTEENTRY)];
	pLogPalette->palVersion	= 0x300;

	for (int ii = 0; ii < 256; ii++)
	{
		pLogPalette->palPalEntry[ii].peRed		= 255; 
		pLogPalette->palPalEntry[ii].peGreen	= 255; 
		pLogPalette->palPalEntry[ii].peBlue		= 255; 
		pLogPalette->palPalEntry[ii].peFlags	= 0; 
	}
	
	HPALETTE hPal = CreatePalette(pLogPalette);
 	SelectPalette(hDC, hPal, TRUE);
	RealizePalette(hDC);

	HBRUSH hBrush	 = CreateSolidBrush(PALETTEINDEX(129));
	HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
	
	Rectangle(hDC, rtGrid.left, rtGrid.top, rtGrid.right, rtGrid.bottom);
	
	SetBkMode(hDC, TRANSPARENT);
	DrawText(hDC, _T("To Paint this rectangle with Solid Brush"), -1, &rtGrid, DT_VCENTER|DT_CENTER|DT_SINGLELINE);

	SelectObject(hDC, hOldBrush);
	RestoreDC(hDC, nSavedDC);

	DeleteObject(hPal);
	delete[] pLogPalette;
	return;
}
